package org.bim.view.drag.design.config;
import lombok.extern.slf4j.Slf4j;
import org.bim.view.drag.design.api.vo.R;
import org.bim.view.drag.design.exception.BizCommonException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.core.annotation.Order;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;


/**
 * 全局异常处理
 *
 * @author huangr
 */
@Order
@Slf4j
@RestControllerAdvice
public class ApiExceptionHandler {

    public static final String MESSAGE = "请求地址:{}";
    public static final String ERROR = "error! ";

    /**
     * 参数校验异常
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public R handleIllegalArgumentsException(IllegalArgumentException ex, HttpServletRequest request) {
        log.warn(ERROR, ex);
        log.warn(MESSAGE, request.getRequestURI());
        return R.fail(ex.getMessage(),1);
    }

    /**
     * 捕获 BindException，用于 validation，如 @NotNull
     */
    @ExceptionHandler(BindException.class)
    public R<Object> handleBindException(BindException ex) {
        String defaultMessage = ex.getAllErrors().get(0).getDefaultMessage();
        final String bizException = "BusinessException";
        if (StringUtils.hasLength(defaultMessage) && defaultMessage.contains(bizException)) {
            defaultMessage = defaultMessage.substring(defaultMessage.indexOf(bizException));
        }
        log.warn(ERROR, ex);
        log.warn(MESSAGE, defaultMessage);
        return R.fail(defaultMessage,409);
    }

    /**
     * 捕获JSR-303异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, HttpServletRequest request) {
        log.warn(ERROR, ex);
        log.warn(MESSAGE, request.getRequestURI());
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder errorMessage = new StringBuilder();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errorMessage.append(fieldError.getDefaultMessage()).append("<br>");
        }
        errorMessage.delete(errorMessage.lastIndexOf("<br>"), errorMessage.length());
        return R.fail( errorMessage.toString(),407);
    }

    /**
     * 参数类型不匹配
     */
    @ExceptionHandler(TypeMismatchException.class)
    public R handleTypeMismatchException(TypeMismatchException ex, HttpServletRequest request) {
        log.warn(ERROR, ex);
        log.warn(MESSAGE, request.getRequestURI());
        return R.fail( ex.getMessage(), 405);
    }


    /**
     * 请求的格式错误，一般是 json 格式错误
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R handleHttpMessageNotReadableException(
            HttpMessageNotReadableException ex, HttpServletRequest request) {
        log.error(ERROR, ex);
        log.error(MESSAGE, request.getRequestURI());
        return R.fail( ex.getMessage(), 406);
    }

    /**
     * 处理SQL异常
     */
    @ResponseBody
    @ExceptionHandler({SQLException.class})
    public R sqlExceptionHandler(SQLException e, HttpServletRequest request) {
        String message = e.getMessage();
        if (message == null) {
            message = e.getClass().getSimpleName();
        }
        log.error(message, e);
        log.error(MESSAGE, request.getRequestURI());
        return R.fail( "SQL异常，请联系管理员",505);

    }
    /**
     * 捕获BizCommonException
     */
    @ExceptionHandler(BizCommonException.class)
    public R handleException(BizCommonException ex, HttpServletRequest request) {
        log.error(ERROR, ex);
        log.error(MESSAGE, request.getRequestURI());
        return R.fail(ex.getMsg(),ex.getCode());
    }
    /**
     * 捕获Exception
     */
    @ExceptionHandler(Exception.class)
    public R handleException(Exception ex, HttpServletRequest request) {
        log.error(ERROR, ex);
        log.error(MESSAGE, request.getRequestURI());
        return R.fail("系统错误",500);
    }
}
